home *** CD-ROM | disk | FTP | other *** search
- package sub_arctic.lib;
-
- import sub_arctic.input.text_acceptor;
- import sub_arctic.input.pressable;
- import sub_arctic.input.simple_draggable;
- import sub_arctic.input.event;
- import sub_arctic.input.focus_dispatch_agent;
- import sub_arctic.input.int_holder;
-
- import sub_arctic.lib.sub_arctic_error;
-
- import java.awt.Font;
-
- /**
- * Single line text edit box. This class allows entry and editing of a
- * single line of text. The text is maintained with a selection or entry
- * point. Selection positions in strings refer to the spaces before the
- * characters (numbered from 0). So for example a selection from 0 to 0
- * places the cursor before the first character (the character at index 0)
- * while a selection from 1 to 2 selects the second character
- * (the character at index 1).
- *
- * @author Scott Hudson
- */
- public class oneline_text_edit extends oneline_text_display
- implements text_acceptor, pressable, simple_draggable {
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- // things left to do:
- // draw non-focus objects differently than the focus
- // think about support for field tabbing (subclass?)
-
- /**
- * Full constructor with explicit width
- * @param int xv x coordinate of this interactor.
- * @param int yv y coordinate of this interactor.
- * @param int wv width of this interactor.
- * @param String init_str the initial string.
- * @param Font fnt the font to use for this interactor.
- * @param boolean boxed true if you want this interactor to have a box
- * around it.
- */
- public oneline_text_edit(
- int xv,
- int yv,
- int wv,
- String init_str,
- Font fnt,
- boolean boxed)
- {
- super(xv,yv,wv,init_str,fnt,boxed);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Full constructor where width is determined by initial string
- * @param int xv x coordinate of this interactor.
- * @param int yv y coordinate of this interactor.
- * @param String init_str the initial string.
- * @param Font fnt the font to use for this interactor.
- * @param boolean boxed true if you want this interactor to have a box
- * around it.
- */
- public oneline_text_edit(
- int xv,
- int yv,
- String init_str,
- Font fnt,
- boolean boxed)
- {
- super(xv,yv,init_str,fnt,boxed);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Constructor with default font and boxed status
- * @param int xv x coordinate of this interactor.
- * @param int yv y coordinate of this interactor.
- * @param String init_str the initial string.
- * @param Font fnt the font to use for this interactor.
- * @param boolean boxed true if you want this interactor to have a box
- * around it.
- */
- public oneline_text_edit(
- int xv,
- int yv,
- String init_str)
- {
- super(xv,yv,init_str);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Constructor with default font and boxed status; we also assume
- * you are going to set the x and y coordinate by other means.
- *
- * @param int xv x coordinate of this interactor.
- * @param int yv y coordinate of this interactor.
- * @param String init_str the initial string.
- * @param Font fnt the font to use for this interactor.
- * @param boolean boxed true if you want this interactor to have a box
- * around it.
- */
- public oneline_text_edit(String init_str)
- {
- super(init_str);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Replace the area of the current selection with the given string. The
- * selection is set to a single point after the new text. Since the
- * the replacement string can be empty, this can be used to delete the
- * selection.
- *
- * @param String with_str the string to replace with.
- */
- public void replace_selection(String with_str)
- {
- String before, after;
- int pos;
-
- /* if they pass a null treat that as an empty string */
- if (with_str == null) with_str = "";
-
- /* if there is no selection, bail out early */
- if (start_of_selection() == NO_SELECTION) return;
-
- /* extract the pieces before and after the selection */
- before = text().substring(0,start_of_selection());
- after = text().substring(end_of_selection(), text().length());
-
- /* concatenate a new string */
- set_text(before + with_str + after);
-
- /* set the selection to a point right after the new text */
- pos = before.length() + with_str.length();
- set_selection(pos,pos);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Delete the character before the current selection (backing the selection
- * up one character). If there is no selection or the selection starts at
- * the beginning of the string, nothing happens.
- */
- public void delete_a_char()
- {
- String before, after;
-
- /* if there is no selection or selection is at beginning, bail now */
- if (start_of_selection() == NO_SELECTION || start_of_selection() == 0)
- return;
-
- /* extract the piece before selection, less one character */
- before = text().substring(0,start_of_selection()-1);
-
- /* extract the piece after the start of the selection */
- after = text().substring(start_of_selection(),text().length());
-
- /* replace the text and move the selection over */
- set_text(before+after);
- set_selection(start_of_selection()-1, end_of_selection()-1);
- ensure_inside(start_of_selection()-1);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Map an x position in local coordinates into a text string position.
- * @return int the position of the point in the string (in characters)
- * @param int xpos the x position to transform (in pixels).
- */
- public int char_pos_of(int xpos)
- {
- int len, front, mid, back, dist;
- char[] the_text;
-
- /* first take off x margin and adjustment */
- xpos -= _h_spacing + x_adjust();
-
- /* take care of positions before start */
- if (xpos < 0) return 0;
-
- /* extract character array from string */
- len = text().length();
- the_text = new char[len];
- text().getChars(0,len,the_text,0);
-
- /* binary search to find the text position before the insert point */
- front = 0;
- back = len;
- do {
- mid = (front + back)/2;
- dist = xpos - _metric.charsWidth(the_text, 0, mid);
- if (dist > 0)
- front = mid;
- else if (dist == 0)
- return mid;
- else
- back = mid;
- } while (front+1 < back);
-
- /* if we are at the end just take that */
- if (mid == len) return front;
-
- /* now see if we are more than 1/2 way into the final character */
- if (Math.abs(xpos - _metric.charsWidth(the_text, 0, front)) >
- Math.abs(xpos-_metric.charsWidth(the_text, 0, front+1)))
- return front + 1;
- else
- return front;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
- /* text_acceptor (input) methods */
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept input that signifies that object is new text focus and will
- * receive subsequent text input. Returns true if the object accepts the
- * focus.
- * @param event evt the start of the text entry event.
- * @param Object user_info the object passed to the agent when we went into
- * the focus set.
- * @return boolean true if we consumed the event, which we always do.
- */
- public boolean start_text_entry(event evt, Object user_info)
- {
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Pre-filter a character before providing it is actually provided as input.
- * This routine gets called to allow the object to modify the character
- * before it is passed to new_char(). Input to the method is the ordinal
- * value of the input character in question along with the modifier mask
- * associated with it. Output should either be the ordinal value of a
- * character or a specific negative value signifying one of several special
- * actions. <p>
- *
- * This routine can be used by subclasses to do a translation (e.g. to all
- * lower case) or to filter out unwanted characters (e.g. everything except
- * decimal digits). Filtering is done by returning the special value
- * DISCARD_CHAR (= -1), which signifies that the character is not to be
- * passed to new_char(). Translation is done by returning the ordinal value
- * of the translated character. In addition, the value CLOSURE_ACTION_CHAR
- * can be returned to indicate that the action_char() method should be
- * invoked instead of new_char(). This is typically done for end of line
- * characters that signify completion of an entry. All modifications to the
- * character are considered local to this object and do not change how the
- * character might be delivered to another object. <p>
- *
- * This routine is not called for cursor movement or other special keys
- * (which are dispatched with special_key()), or characters classified
- * as edit keys (e.g. to delete a character or line). The text input
- * dispatch agent class (text_agent) provides several standard filters
- * that can be called for common operations.
- *
- * @param int input_char the char that was hit.
- * @param int modifiers state of the modifier keys.
- * @return int the character to insert or a special value (DISCARD_CHAR or
- * CLOSURE_ACTION_CHAR).
- */
- public int char_filter(int input_char, int modifiers)
- {
- /* here we do no filtering and no translation */
- return input_char;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept input for a single character. Returns true if the object
- * consumes the character.
- *
- * @param event evt the input event (normally a keypress) .
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we accepted this character.
- */
- public boolean new_char(event evt, char ch, Object user_info)
- {
- /* if we have no selection, make one at the end */
- if (start_of_selection() == NO_SELECTION)
- set_selection(SELECT_END,SELECT_END);
-
- /* replace selection with the char */
- replace_selection(String.valueOf(ch));
-
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept input for a character that has been classified as a closure
- * action (by returning CLOSURE_ACTION_CHAR from char_filter). Returns
- * true if the object consumes the character.
- *
- * @param event evt the input event (normally a keypress).
- * @param char ch the action character in question.
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this character.
- */
- public boolean action_char(event evt, char ch, Object user_info)
- {
- /* Here we consume, but ignore closure characters */
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept input for a character signifying a delete. Returns true if the
- * object consumes the input.
- *
- * @param event evt the input event (normally a keypress).
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this delete character.
- */
- public boolean delete_char(event evt, Object user_info)
- {
- /* if we have no selection, we do nothing */
- if (start_of_selection() == NO_SELECTION)
- return true;
-
- /* if we have a point selection delete back from it */
- if (start_of_selection() == end_of_selection())
- delete_a_char();
- /* otherwise replace selection with an empty string */
- else
- replace_selection("");
-
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept input for a character signifying a line kill. Returns true if
- * the object consumes the input. Currently a ^U ('\025') is treated as
- * a line kill. This behavior can be changed via the text input dispatch
- * agent. (Unfortunately, AWT does not currently provide a way to determine
- * the user's edit character preferences, so this is the best we can do.)
- *
- * @param event evt the input event (normally a keypress).
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this line kill.
- */
- public boolean line_kill(event evt, Object user_info)
- {
- /* select the whole text, then remove it */
- set_selection(0, SELECT_END);
- replace_selection("");
-
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /** Accept input for a key press signifying a special key (corresponding
- * to KEY_ACTION events). Values passed here are from the key field of the
- * events. These include: DOWN, END, F1, ..., F12, HOME, LEFT, PGDN, PGUP,
- * RIGHT, and UP. Returns true if the object consumes the event.
- *
- * @param event evt the input event (normally a key_action event).
- * @param int key_code the special key in question.
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this special key.
- */
- public boolean special_key(event evt, int key_code, Object user_info)
- {
-
- /* handle LEFT and RIGHT only */
- if (key_code == event.LEFT)
- {
- /* if we have no selection, we are done */
- if (start_of_selection() == NO_SELECTION) return false;
-
- /* if we have a point selection, just move */
- if (start_of_selection() == end_of_selection())
- {
- if (start_of_selection() != 0)
- set_selection(start_of_selection()-1, start_of_selection()-1);
- }
- /* otherwise go to a point selection at the left */
- else
- set_selection(start_of_selection(), start_of_selection());
-
- return true;
- }
-
- if (key_code == event.RIGHT)
- {
- /* if we have no selection, we are done */
- if (start_of_selection() == NO_SELECTION) return false;
-
- /* if we have a point selection, just move */
- if (start_of_selection() == end_of_selection())
- set_selection(start_of_selection()+1, start_of_selection()+1);
- /* otherwise go to a point selection at the right */
- else
- set_selection(end_of_selection(), end_of_selection());
-
- return true;
- }
-
- /* we don't want anything else */
- return false;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Dispatch input indicating that text input is over (e.g. the text focus
- * has moved elsewhere. Returns true if the object consumes the input.
- *
- * @param event evt the input event.
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this event.
- */
- public boolean end_text_entry(event evt, Object user_info)
- {
- /* here we do nothing */
- return true;
-
- // later we need to go to another highlight style
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
- /* pressable (input) methods */
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept mouse button press input to the object. Return true is event
- * was consumed.
- *
- * @param event evt the input event.
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this event.
- */
- public boolean press(event evt, Object user_info)
- {
- /* make us both the text and drag focus */
- manager.text_focus.set_focus_to(this, evt, user_info);
- manager.simple_drag_focus.set_focus_to(this, evt, new int_holder(0));
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Companion method to press() needed to finish pressable. Here we never
- * consume the event.
- *
- * @param event evt the input event.
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this event.
- */
- public boolean release(event evt, Object user_info)
- {
- return false;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
- /* simple_draggable (input) methods */
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept the start of a drag to the object.
- *
- * @param event evt the input event.
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this event.
- */
- public boolean drag_start(event evt, Object user_info)
- {
- int pos;
-
- /* establish the start of selection where this event was */
- pos = char_pos_of(evt.local_x());
- set_selection(pos,pos);
-
- /* remember the start position */
- ((int_holder)user_info).value = pos;
-
- return true;
-
- //later need to handle "extend" case (w/ shift down)
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept a movement during a drag.
- *
- * @param event evt the input event.
- * @param Object user_info the object passed to the agent when this object
- * entered the focus set.
- * @boolean true if we handled this event
- */
- public boolean drag_feedback(event evt, Object user_info)
- {
- int pos;
-
- /* set end of selection here (we rely on set_selection() to flip) */
- pos = char_pos_of(evt.local_x());
- set_selection(((int_holder)user_info).value, pos);
- ensure_inside(pos);
-
- return true;
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
-
- /**
- * Accept input corresponding to the end of a drag.
- *
- * @param event evt the input event.
- * @param Object user_info the object passed to the agent when this
- * object entered the focus set.
- * @boolean true if we handled this event.
- */
- public boolean drag_end(event evt, Object user_info)
- {
- /* let drag_feedback do the work */
- return drag_feedback(evt, user_info);
- }
-
- /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */
- }
-
- /*=========================== COPYRIGHT NOTICE ===========================
-
- This file is part of the subArctic user interface toolkit.
-
- Copyright (c) 1996 Scott Hudson and Ian Smith
- All rights reserved.
-
- The subArctic system is freely available for most uses under the terms
- and conditions described in
- http://www.cc.gatech.edu/gvu/ui/sub_arctic/sub_arctic/doc/usage.html
- and appearing in full in the lib/interactor.java source file.
-
- The current release and additional information about this software can be
- found starting at: http://www.cc.gatech.edu/gvu/ui/sub_arctic/
-
- ========================================================================*/
-